import java.awt.Point;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class TextFieldEventProcessor extends DrawObjectEventProcessor
{
    private void CreateTextFieldArray(Point Pos, String LoadPath, boolean LeftRightOrTopDown, ObjectStorage Objects)
    {
        if (LoadPath != null && (new File(LoadPath)).exists())
        {
            try (BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(LoadPath))))
            {
                int TextFieldPosxNext = Pos.x;
                int TextFieldPosyNext = Pos.y;
                int GridSizex = 50; // TODO: don't hard code
                int GridSizey = 50; // TODO: don't hard code

                while (true)
                {
                    String Line = is.readLine();
                    if (Line == null)
                    {
                        is.close();
                        break;
                    }
                    if (Line.length() >= 1)
                    {
                        Point PlacePosSub = new Point(Pos.x, Pos.y);

                        TextField TextFieldAdded = (TextField) Objects.AddObject("TextField", PlacePosSub, null);

                        TextFieldAdded.SetText(Line);
                        TextFieldAdded.SetPos(new Point(TextFieldPosxNext, TextFieldPosyNext));

                        if (LeftRightOrTopDown)
                        {
                            TextFieldPosxNext = TextFieldPosxNext + (int) (TextFieldAdded.Size.x / GridSizex) * GridSizex + GridSizex;
                        }
                        else
                        {
                            TextFieldPosyNext = TextFieldPosyNext + (int) (TextFieldAdded.Size.y / GridSizey) * GridSizey + GridSizey;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // ignore, maybe file locked, user sees that nothing is loaded into TextFields
            }
        }
    }

    @Override
    public void TryProcessUserKeyboardAction(MainWindow.GUIElements GUIElements, KeyEventProcessor KeyEventProcessor, MouseEventProcessor MouseEventProcessor, ObjectStorage ObjectStorage, IOProgram IOProgram)
    {
        /*
        // ****************************************************************
        // TextField edit mode (old, Beta 1)
        if (DEFINED(FillTextField))
        {
        	if (KeyEventProcessor.IsKeyCodePressed(KeyEvent.VK_ENTER))
        	{
        		if (((TextField) FillTextField).GetText().length() >= 1)
        		{
        			TextField TextField = ((TextField) FillTextField);
        
        			TextField.SetBeingEdited(false);
        
        			FillTextField = UNDEFINED;
        
        			if (FillTextField_TextUnchanged != null && FillTextField_TextUnchanged.length() >= 1 && // first two conditions should always be the case
        				!(FillTextField_TextUnchanged.equals(DrawObject.TextFieldDefaultText)) && !(FillTextField_TextUnchanged.equals(TextField.GetText()))) // not the same text entered again?
        			{
        				String TextFieldTextOld = FillTextField_TextUnchanged;
        				String TextFieldTextNew = TextField.GetText();
        
        				ArrayList<TextField> TextFieldsWithSameText = ObjectStorage.GetTextFieldsByText(TextFieldTextOld);
        				if (TextFieldsWithSameText.size() >= 1) // the original one already has the new text, so >= 1 means WERE there two TextFields with this text?
        				{
        					if (Tools.ShowYesNoDialog(
        						GUIElements.GetMainWindow(),
        						"There are several TextFields on which the same text change could be applied.\r\n" + "Update all of them?\r\n" + "Notice one activated TextField always activates all others with same text during simulation."
        					))
        					{
        						for (int m = 0; m < TextFieldsWithSameText.size(); m++)
        							TextFieldsWithSameText.get(m).SetText(TextFieldTextNew);
        					}
        				}
        			}
        
        			GUIElements.GetMainWindow().DoRedraw();
        		}
        		else
        		{
        			GUIElements.GetMainWindow().GetTitleBarInfo().AddInfoText("You must enter any text!", true, false, false, false);
        		}
        	}
        	else if (KeyEventProcessor.IsKeyCodePressed(0x08)) // backspace
        	{ // buggy, deletes TWO letters at once
        	
        		((TextField) FillTextField).RemoveOneLetter();
        
        		GUIElements.GetMainWindow().DoRedraw();
        	}
        	else if (KeyEventProcessor.AnyKeyTyped())
        	{
        		if ((int) (KeyEventProcessor.GetKeyTyped()) >= 32 && // all non-printable control chars are below space (#32), except Del (#127), if user presses Del, Shift, Tab, 65535 is returned (tested)
        			(int) (KeyEventProcessor.GetKeyTyped()) != 127 && (int) (KeyEventProcessor.GetKeyTyped()) <= 255) // https://theasciicode.com.ar/
        		{
        			((TextField) FillTextField).AddText(KeyEventProcessor.GetKeyTyped());
        
        			GUIElements.GetMainWindow().DoRedraw();
        		}
        	}
        }
        */
        // ****************************************************************

        if (!(KeyboardEventsToBeProcessed(GUIElements)))
            return;

        // ****************************************************************
        // a (create TextField array)
        if (KeyEventProcessor.IsKeyCodePressed(KeyEvent.VK_A) &&
            KeyEventProcessor.IsControlPressed())
        {
            String LoadPath = Tools
                .ShowInputDialog("Path to file containing TextFields' text line-by-line?\r\n(enter just a file name to load from working directory \"" + Settings.GetWorkingDirectory() + "\",\r\nput in front '-' to line up top down)");

            boolean LeftRightOrTopDown = true;

            if (LoadPath != null)
            {
                if (LoadPath.indexOf('-') == 0)
                {
                    LeftRightOrTopDown = false;
                    LoadPath = LoadPath.substring(1);
                }
                else
                {
                    LeftRightOrTopDown = true;
                }
            }

            if (LoadPath != null && LoadPath.indexOf("/") < 0 && LoadPath.indexOf("\\") < 0)
                LoadPath = (Settings.GetWorkingDirectory() + "/" + LoadPath).replace("//", "/");

            if (LoadPath != null && LoadPath.length() >= 1)
            {
                CreateTextFieldArray(
                    DrawObject.AlignOnGrid(DrawObject.UnZoomPoint(MouseEventProcessor.GetMousePosPoint(GUIElements.GetMainWindow()))),
                    LoadPath,
                    LeftRightOrTopDown,
                    ObjectStorage
                );

                GUIElements.GetMainWindow().DoRedraw();
            }
        }
        // ****************************************************************
        // n (negate NeuronInputField)
        if (KeyEventProcessor.IsKeyTyped('e'))
        {
            if (MultiSelectionExisting)
            {
                ArrayList<DrawObject> MultiSelectionObjects = ObjectStorage.GetMultiSelectionObjects();

                for (int m = 0; m < MultiSelectionObjects.size(); m++)
                {
                    DrawObject o = MultiSelectionObjects.get(m);
                    if (o.IsTextField())
                    {
                        ((TextField) o).Toggle();
                    }
                }

                GUIElements.GetMainWindow().DoRedraw();
            }
            else if (DEFINED(NearObject))
            {
                if (NearObject.IsTextField())
                {
                    ((TextField) NearObject).Toggle();

                    GUIElements.GetMainWindow().DoRedraw();
                }
            }
        }
        // ****************************************************************
        // n (negate NeuronInputField)
        if (KeyEventProcessor.IsKeyTyped('n'))
        {
            if (MultiSelectionExisting)
            {
                ArrayList<DrawObject> MultiSelectionObjects = ObjectStorage.GetMultiSelectionObjects();

                for (int m = 0; m < MultiSelectionObjects.size(); m++)
                {
                    DrawObject o = MultiSelectionObjects.get(m);
                    if (o.IsTextField())
                    {
                        ((TextField) o).ToggleIsNegative();
                    }
                }

                GUIElements.GetMainWindow().DoRedraw();
            }
            else if (DEFINED(NearObject))
            {
                if (NearObject.IsTextField())
                {
                    ((TextField) NearObject).ToggleIsNegative();

                    GUIElements.GetMainWindow().DoRedraw();
                }
            }
        }
    }

    @Override
    public void TryProcessUserMouseAction(MainWindow.GUIElements GUIElements, KeyEventProcessor KeyEventProcessor, MouseEventProcessor MouseEventProcessor, ObjectStorage ObjectStorage, IOProgram IOProgram)
    {
        if (!(MouseEventsToBeProcessed(GUIElements)))
            return;

        // ****************************************************************
        if (MouseEventProcessor.IsRightButtonClicked())
        {
            if (MultiSelectionExisting)
            {
                // new in Beta 3:
                ArrayList<DrawObject> MultiSelectionObjects = ObjectStorage.GetMultiSelectionObjects();
                if (MultiSelectionObjects.size() >= 1)
                {
                    String TextFilePath = Tools.PromptLoadFile(
                        "Read TextFields' text line by line from .txt file...",
                        Settings.GetWorkingDirectory()
                    );

                    if (TextFilePath != null && TextFilePath.length() >= 1 && (new File(TextFilePath)).exists())
                    {
                        String TextFileFileName;

                        if (TextFilePath.lastIndexOf("/") >= 0)
                            TextFileFileName = TextFilePath.substring(TextFilePath.lastIndexOf("/") + 1);
                        else if (TextFilePath.lastIndexOf("\\") >= 0)
                            TextFileFileName = TextFilePath.substring(TextFilePath.lastIndexOf("\\") + 1);
                        else
                            TextFileFileName = TextFilePath;

                        String TextTypeDescription;

                        if (TextFileFileName.lastIndexOf(".") >= 0)
                            TextTypeDescription = TextFileFileName.substring(0, TextFileFileName.lastIndexOf("."));
                        else
                            TextTypeDescription = TextFileFileName;

                        String[] TextFileLines = Tools.ReadFileLines(TextFilePath); // returns all non-empty lines only

                        int TextFieldCount = 0;
                        for (int i = 0; i < MultiSelectionObjects.size(); i++)
                            if (MultiSelectionObjects.get(i) instanceof TextField)
                                TextFieldCount++;

                        if ((TextFieldCount >= TextFileLines.length) ||
                            (Tools.ShowYesNoDialog(
                                GUIElements.GetMainWindow(),
                                "There are not enough TextFields (" + TextFieldCount +
                                    ") to take up all (" + TextFileLines.length +
                                    ") lines from .txt file. Drop (" + (TextFileLines.length - TextFieldCount) + ") lines from .txt file?"
                            ) == true))
                        {
                            int TextFileLineIndex = 0;

                            for (int i = 0; i < MultiSelectionObjects.size(); i++)
                            {
                                if (MultiSelectionObjects.get(i) instanceof TextField)
                                {
                                    TextField o = ((TextField) MultiSelectionObjects.get(i));
                                    if (TextFileLineIndex < TextFileLines.length)
                                    {
                                        String TextNew = TextTypeDescription + ":" + TextFileLines[TextFileLineIndex];
                                        o.SetText(TextNew);
                                    }
                                    else
                                    {
                                        String TextNew = TextTypeDescription + ":" + "unset_" + (TextFileLineIndex - TextFileLines.length + 1);
                                        o.SetText(TextNew);
                                    }
                                    TextFileLineIndex++;
                                }
                            }

                            GUIElements.GetMainWindow().DoRedraw();
                        }
                    }
                }
                // end of new in Beta 3
            }
            else if (DEFINED(SingleSelectedObject))
            {
                if (SingleSelectedObject.IsTextField())
                {
                    FillTextField = SingleSelectedObject;
                    FillTextField_TextUnchanged = ((TextField) FillTextField).GetText();

                    // old (Beta 1):
                    /*
                    ((TextField) FillTextField).Clear();
                    ((TextField) FillTextField).SetBeingEdited(true);
                    */

                    // new (Beta 2):
                    String TextNew = Tools.ShowInputDialog("Enter new TextField text:", FillTextField_TextUnchanged);

                    if (TextNew != null && TextNew.length() >= 1)
                    {
                        TextField TextField = ((TextField) FillTextField);

                        TextField.SetText(TextNew);

                        FillTextField = UNDEFINED;

                        if (FillTextField_TextUnchanged != null && FillTextField_TextUnchanged.length() >= 1 && // first two conditions should always be the case
                            !(FillTextField_TextUnchanged.equals(DrawObject.TextFieldDefaultText)) && !(FillTextField_TextUnchanged.equals(TextField.GetText()))) // not the same text entered again?
                        {
                            String TextFieldTextOld = FillTextField_TextUnchanged;
                            String TextFieldTextNew = TextField.GetText();

                            ArrayList<TextField> TextFieldsWithSameText = ObjectStorage.GetTextFieldsByText(TextFieldTextOld);
                            if (TextFieldsWithSameText.size() >= 1) // the original one already has the new text, so >= 1 means WERE there two TextFields with this text?
                            {
                                if (Tools.ShowYesNoDialog(
                                    GUIElements.GetMainWindow(),
                                    "There are several TextFields on which the same text change could be applied.\r\n" + "Update all of them?\r\n" + "Notice one activated TextField always activates all others with same text during simulation."
                                ))
                                {
                                    for (int m = 0; m < TextFieldsWithSameText.size(); m++)
                                        TextFieldsWithSameText.get(m).SetText(TextFieldTextNew);
                                }
                            }
                        }
                    }
                    else
                    {
                        FillTextField = UNDEFINED;
                    }

                    GUIElements.GetMainWindow().DoRedraw();
                    // end of new (Beta 2)
                }
            }
        }

        // ****************************************************************
        if (DEFINED(FillTextField))
        {
            GUIElements.GetMainWindow().GetTitleBarInfo().AddInfoText(FillTextFieldMessage, false, false, true, false);
        }
        else
        {
            GUIElements.GetMainWindow().GetTitleBarInfo().RemoveInfoText(FillTextFieldMessage);
        }

        return;
    }
}
